// boolean-weight.h

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Copyright 2011 Paul R. Dixon
// Author: paul@edobashira.com
// www.edobashira.com


#include <fst/weight.h> //For the constant definitions

namespace fst {

class BooleanWeight {
  bool value_;
 public:
	
	typedef BooleanWeight ReverseWeight;

  BooleanWeight() {    
  }

  BooleanWeight(bool value) {
    value_ = value;
  }

	//Undocumented
  static const string &Type() {
    static const string type = "boolean";
    return type;
  }

  static const BooleanWeight Zero() {
    return BooleanWeight(false);
  }

  static const BooleanWeight One() {
    return BooleanWeight(true);
  }

  inline bool Value() const {
    return value_;
  }

  std::istream &Read(std::istream &strm) {
    return ReadType(strm, &value_);
  }

  std::ostream &Write(std::ostream &strm) const {
    return WriteType(strm, value_);
  }

	size_t Hash() const {
		return value_ ? 1 : 0;
	}

	BooleanWeight Quantize(float delta = kDelta) const {
		return *this;
	}
	
	BooleanWeight Reverse() const { return *this; }

	static uint64 Properties() {
		return  kLeftSemiring | kRightSemiring | kCommutative |
        kPath | kIdempotent;
	}
};

//w must be const!!
inline std::ostream &operator<<(std::ostream &strm, const BooleanWeight &w) {
  if (w.Value())
    return strm << "true";
  else
    return strm << "false";
}

inline istream &operator>>(istream &strm, BooleanWeight &w) {
  string s;
  strm >> s;
  if (s == "true" || s == "1") {
    w = BooleanWeight(true);
  } else if (s == "false" || s == "0") {
    w = BooleanWeight(false);
  } else {
    LOG(FATAL) << "Invalid Boolean weight value " << s;
  }
  return strm;
}

inline BooleanWeight Plus(const BooleanWeight &w1,
                          const BooleanWeight &w2) {
  return w1.Value() || w2.Value();
}

inline BooleanWeight Times(const BooleanWeight &w1,
                          const BooleanWeight &w2) {
  return w1.Value() && w2.Value();
}

//Undocumented
inline bool operator!=(const BooleanWeight &w1,
                       const BooleanWeight &w2) {
  return w1.Value() != w2.Value();
}

//Undocumented
inline bool operator==(const BooleanWeight &w1,
                       const BooleanWeight &w2) {
  return w1.Value() == w2.Value();
}


inline BooleanWeight Divide(const BooleanWeight &w1,
                            const BooleanWeight &w2,
                            DivideType typ = DIVIDE_ANY) {  
	return BooleanWeight(w1.Value() - w2.Value());
}

inline bool ApproxEqual(const BooleanWeight &w1,
                        const BooleanWeight &w2,
                        float delta = kDelta) {
  return w1.Value() == w2.Value();
}

}



